﻿using IOP.SgrA;
using IOP.SgrA.ECS;
using IOP.Extension.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;

namespace VkSample113;

public class TreeSystem : ComponentSystem
{
    private float wind_speed;
    private float wind_force;
    private float bend_R;
    private float bend_R_min = 500;
    private float bend_R_max = 10000;
    private float wind_speed_init = 200;
    private float wind_force_init2 = -4.0f;
    private float wind_force_init = -2.0f;
    private float direction_degree = 30;
    Vector3[] TrunkPosition = new Vector3[4]
    { 
        new Vector3(), 
        new Vector3(-50f, 0, 50f), 
        new Vector3(-100f,0,0), 
        new Vector3(-150f,0,0)
    };
    private PriorityQueue<Context, float> LeafQueue = new PriorityQueue<Context, float>();

    private IRenderGroup? LeafGroup;

    [Autowired]
    private IGraphicsManager? GraphicsManager { get; set; }

    public override void Initialization()
    {
        base.Initialization();
        GraphicsManager?.TryGetRenderGroup("TreeLeaves", out LeafGroup);
        var leafArchetype = ContextManager.CreateArchetype("TreeLeaves", new LeafComponent());

        ContextManager.Foreach<TrunkGroup>((group, index) =>
        {
            Context context = ContextManager.GetContext(group.Entity);
            group.Trunk.Transform.Position = TrunkPosition[index];
            IRenderObject render = context.GetContextRenderObject();
            ITexture? texture = render.GetComponents<ITexture>().Where(x => x.SetIndex == 0 && x.Binding == 0).FirstOrDefault();
            texture?.UpdateTextureMemoryData(new UniformTree() { BendR = bend_R_max, DirectionDegree = direction_degree });
            foreach(var item in render.GetChildrens())
            {
                ContextManager.CreateContexts(context, 1, leafArchetype, LeafGroup, item);
            }
            return group;
        });
    }

    public override void Update(TimeSpan lastStamp)
    {
        wind_speed += wind_force * (float)lastStamp.TotalSeconds * 50;//摆动的速度
        bend_R -= wind_speed * (float)lastStamp.TotalSeconds * 50;//摆动的幅度
        if (bend_R <= bend_R_min)
        {
            wind_force = wind_force_init2;
        }
        if (bend_R > bend_R_max)//更改状态
        {
            wind_speed = wind_speed_init;
            bend_R = bend_R_max;
            wind_force = wind_force_init;
        }
        ContextManager.Foreach<TrunkGroup>((group) =>
        {
            Context context = ContextManager.GetContext(group.Entity);
            ref MVPMatrix mvp = ref context.GetMVPMatrix();
            mvp.ModelMatrix = Matrix4x4.CreateTranslation(group.Trunk.Transform.Position);
            IRenderObject render = context.GetContextRenderObject();
            ITexture? texture = render.GetComponents<ITexture>().Where(x => x.SetIndex == 0 && x.Binding == 0).FirstOrDefault();
            texture?.UpdateTextureMemoryData(new UniformTree() { BendR = bend_R, DirectionDegree = direction_degree });
            CalculatePosition(context, group.Trunk.Transform.Position, context.Camera, bend_R, direction_degree);
            context.PushToRenderGroup();
        });
        while(LeafQueue.TryDequeue(out Context? context, out float d))
        {
            ref MVPMatrix mvp = ref context.GetMVPMatrix();
            IRenderObject render = context.GetContextRenderObject();
            var trans = render.GetTransform();
            mvp.ModelMatrix = Matrix4x4.CreateFromQuaternion(trans.Rotation) * Matrix4x4.CreateTranslation(trans.Position);
            context.PushToRenderGroup();
        }
    }

    private void CalculatePosition(Context parent, Vector3 center, Camera camera, float bend_RIn, float direction_degreeIn)
    {
        foreach(var item in parent.GetChildrens())
        {
            IRenderObject render = item.GetContextRenderObject();
            var trans = render.GetTransform();
            var init = render.GetComponents<LeafTransform>().First();
            Vector3 r = center + init.InitPosition;
            float curr_radian = r.Y / bend_RIn; //计算当前的弧度
            r.Y = bend_RIn * MathF.Sin(curr_radian);//计算当前中心点Y 坐标
            float pianDistance = (float)(bend_RIn - bend_RIn * MathF.Cos(curr_radian));//计算结果的偏移距离
            r.X += pianDistance * MathF.Sin(toRadians(direction_degreeIn)); //计算当前中心点X 坐标
            r.Z += pianDistance * MathF.Cos(toRadians(direction_degreeIn)); //计算当前中心点Z 坐标
            float d = (r - camera.EyePosition).Length();
            LeafQueue.Enqueue(item, -d);

            curr_radian = Constant.TREE_HEIGHT / bend_R;
            float result_Y = (float)(bend_R * MathF.Sin(curr_radian));
            pianDistance = (float)(bend_R - bend_R * MathF.Cos(curr_radian));
            float result_X = (float)(center.X + pianDistance * MathF.Sin(toRadians(direction_degreeIn)));//计算结果的X 分量
            float result_Z = (float)(center.Z + pianDistance * MathF.Cos(toRadians(direction_degreeIn))); //计算结果的Z 分量
            float rX = (float)MathF.Cos(toRadians(direction_degreeIn));
            float rZ = (float)MathF.Sin(toRadians(direction_degreeIn));
            float angle = -curr_radian;
            trans.Position = new Vector3(result_X, result_Y, result_Z);
            trans.Rotation = Quaternion.CreateFromAxisAngle(new Vector3(-rX, 0, rZ), angle) * init.InitRotation;
        }
    }

    private float toRadians(float degree)
    {//角度转换成弧度的方法
        return (float)degree * MathF.PI / 180;
    }
}

public struct TrunkGroup
{
    public Entity Entity;
    public TrunkComponent Trunk;
}

public struct LeafGroup
{

}

public struct UniformTree
{
    public float BendR;
    public float DirectionDegree;
}
